Number.prototype.toRad = function () { return this * Math.PI / 180; }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/* Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2012             */
/*                                                                                                */
/* from: Vincenty inverse formula - T Vincenty, "Direct and Inverse Solutions of Geodesics on the */
/*       Ellipsoid with application of nested equations", Survey Review, vol XXII no 176, 1975    */
/*       http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf                                             */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */

/**
 * Calculates geodetic distance between two points specified by latitude/longitude using 
 * Vincenty inverse formula for ellipsoids
 *
 * @param   {Number} lat1, lon1: first point in decimal degrees
 * @param   {Number} lat2, lon2: second point in decimal degrees
 * @returns (Number} distance in metres between points
 */
function distVincenty(lat1, lon1, lat2, lon2) {
  var a = 6378137, b = 6356752.314245,  f = 1/298.257223563;  // WGS-84 ellipsoid params
  var L = (lon2-lon1).toRad();
  var U1 = Math.atan((1-f) * Math.tan(lat1.toRad()));
  var U2 = Math.atan((1-f) * Math.tan(lat2.toRad()));
  var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
  var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
  
  var lambda = L, lambdaP, iterLimit = 100;
  do {
    var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
    var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + 
      (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
    if (sinSigma==0) return 0;  // co-incident points
    var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
    var sigma = Math.atan2(sinSigma, cosSigma);
    var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
    var cosSqAlpha = 1 - sinAlpha*sinAlpha;
    var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
    if (isNaN(cos2SigmaM)) cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (§6)
    var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
    lambdaP = lambda;
    lambda = L + (1-C) * f * sinAlpha *
      (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
  } while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);

  if (iterLimit==0) return NaN  // formula failed to converge

  var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
  var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
  var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
  var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
    B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
  var s = b*A*(sigma-deltaSigma);
  
  s = s.toFixed(3); // round to 1mm precision
  return s;
  
  // note: to return initial/final bearings in addition to distance, use something like:
  var fwdAz = Math.atan2(cosU2*sinLambda,  cosU1*sinU2-sinU1*cosU2*cosLambda);
  var revAz = Math.atan2(cosU1*sinLambda, -sinU1*cosU2+cosU1*sinU2*cosLambda);
  return { distance: s, initialBearing: fwdAz.toDeg(), finalBearing: revAz.toDeg() };
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */


function getDistance(llon1, llat1, llon2, llat2){
	var rad = 6372795;
	//var rad = 6378137;
	var lat1 = llat1*Math.PI/180;
	var lat2 = llat2*Math.PI/180;
	var lon1 = llon1*Math.PI/180;
	var lon2 = llon2*Math.PI/180;
	
	var delta = lon2 - lon1;
	var cl1 = Math.cos(lat1)
	var cl2 = Math.cos(lat2)
	var sl1 = Math.sin(lat1)
	var sl2 = Math.sin(lat2)
	var cdelta = Math.cos(delta)
	var sdelta = Math.sin(delta)
	
	var y = Math.sqrt(Math.pow(cl2*sdelta,2)+Math.pow(cl1*sl2-sl1*cl2*cdelta,2))
	var x = sl1*sl2+cl1*cl2*cdelta
	var ad = Math.atan2(y,x)
	var dist = ad*rad
	
	return dist;
}

/*
getDistance(-139.398, 77.1539, -139.55, -77.1804);
getDistance(120.398, 77.1539, 129.55, 77.1804);
getDistance(-120.398, 77.1539, 129.55, 77.1804);
getDistance(0, 0, -52, 80);

L.latLng(0,0).distanceTo(L.latLng(80, -52));
*/





function getInRadius(target, radius, l){
	var result = new Array();
	for (var i = 0; i < l.length; i++){
		if(l[i].geometry&&l[i].geometry.type==="Point"){
			var dst = getDistance(target.lon, target.lat, l[i].geometry.coordinates[0], l[i].geometry.coordinates[1]);
			//alert(l[i].name + " " + dst);
			console.log(l[i].name + " " + dst + " " + l[i].geometry.coordinates[0] + " " + l[i].geometry.coordinates[1]);
			if (dst < radius){
				//result.push(l[i]);
				
				l[i].show_on_map = true;
			} else {
				l[i].show_on_map = false;
			}
		}
	}
	//return result;
}


var m1 = getDistance(-139.398, 77.1539, -139.55, -77.1804);
var l1 = L.latLng(77.1539,-139.398).distanceTo(L.latLng(-77.1804, -139.55));
var mid = (m1+l1)/2.0;
var dv = distVincenty(77.1539,-139.398,-77.1804, -139.55);
diff1 = Math.abs(dv-m1);
diff2 = Math.abs(dv-l1);

//console.log("My: " + m1 + " LeafLet: " + l1 + " difference: " + Math.abs(m1-l1) + " % from middle: " + Math.abs(m1-l1)*100/mid);
console.log("My %%: " + diff1*100/dv + " LeafLet %%: " + diff2*100/dv);

m1 = getDistance(120.398, 77.1539, 129.55, 77.1804);
l1 = L.latLng(77.1539, 120.398).distanceTo(L.latLng(77.1804, 129.55));
mid = (m1+l1)/2.0;
dv = distVincenty(77.1539, 120.398, 77.1804, 129.55);
diff1 = Math.abs(dv-m1);
diff2 = Math.abs(dv-l1);

//console.log("My: " + m1 + " LeafLet: " + l1 + " difference: " + Math.abs(m1-l1) + " % from middle: " + Math.abs(m1-l1)*100/mid);
console.log("My %%: " + diff1*100/dv + " LeafLet %%: " + diff2*100/dv);

m1 = getDistance(-120.398, 77.1539, 129.55, 77.1804);
l1 = L.latLng(77.1539, -120.398).distanceTo(L.latLng(77.1804, 129.55));
mid = (m1+l1)/2.0;
dv = distVincenty(77.1539, -120.398, 77.1804, 129.55);
diff1 = Math.abs(dv-m1);
diff2 = Math.abs(dv-l1);

//console.log("My: " + m1 + " LeafLet: " + l1 + " difference: " + Math.abs(m1-l1) + " % from middle: " + Math.abs(m1-l1)*100/mid);
console.log("My %%: " + diff1*100/dv + " LeafLet %%: " + diff2*100/dv);

m1 = getDistance(0, 0, 0.2, 0.2);
l1 = L.latLng(0, 0).distanceTo(L.latLng(0.2, 0.2));
mid = (m1+l1)/2.0;
dv = distVincenty(0, 0, 0.2, 0.2);
diff1 = Math.abs(dv-m1);
diff2 = Math.abs(dv-l1);

//console.log("My: " + m1 + " LeafLet: " + l1 + " difference: " + Math.abs(m1-l1) + " % from middle: " + Math.abs(m1-l1)*100/mid);
console.log("My %%: " + diff1*100/dv + " LeafLet %%: " + diff2*100/dv);

m1 = getDistance(0, 0, 0.0000001, 0.0000001);
l1 = L.latLng(0, 0).distanceTo(L.latLng(0.0000001, 0.0000001));
mid = (m1+l1)/2.0;
dv = distVincenty(0, 0, 0.0000001, 0.0000001);
diff1 = Math.abs(dv-m1);
diff2 = Math.abs(dv-l1);

//console.log("My: " + m1 + " LeafLet: " + l1 + " difference: " + Math.abs(m1-l1) + " % from middle: " + Math.abs(m1-l1)*100/mid);
console.log("My %%: " + diff1*100/dv + " LeafLet %%: " + diff2*100/dv);
/*
var target = {"lon" : 0, "lat": 0};

getInRadius(target, 1000,  featureCollections.features);
*/